package com.matt.service.impl;

import com.matt.domain.Classes;
import com.matt.domain.TargetObject;
import com.matt.domain.course.CoursePlanTopic;
import com.matt.domain.course.CourseTopic;
import com.matt.domain.rel.RelClassesCourseTopic;
import com.matt.foundation.DO.ClassesTopicDO;
import com.matt.commons.exception.BusinessException;

import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.query.CourseTopicQuery;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.vo.classes.ClassesVo;
import com.matt.foundation.vo.course.CourseTopicPageVo;
import com.matt.foundation.vo.course.WebCourseTopicClassesVo;
import com.matt.repository.TargetObjectRepository;
import com.matt.repository.base.ClassesCourseTopicRepository;
import com.matt.repository.base.TargetObjectCourseRepository;
import com.matt.repository.course.CoursePlanTopicRepository;
import com.matt.repository.course.CourseTopicRepository;
import com.matt.repository.rel.RelClassesCourseTopicRepository;
import com.matt.service.ClassesService;
import com.matt.service.CoursePlanTopicService;
import com.matt.service.CourseTopicService;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.model.ErrorCode.TOPIC_DATE_CANNOT_MODIFY;
import static com.matt.foundation.model.ErrorCode.TOPIC_DATE_DUPLICATE;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2018/3/8
 * *******************************
 */
@Service
@Slf4j
public class CourseTopicServiceImpl implements CourseTopicService {

    @Autowired
    private CourseTopicRepository courseTopicRepository;

    @Autowired
    private TargetObjectRepository targetObjectRepository;

    @Autowired
    private TargetObjectCourseRepository targetObjectCourseRepository;

    @Autowired
    private CoursePlanTopicRepository coursePlanTopicRepository;

    @Autowired
    private ClassesService classesService;

    @Autowired
    private RelClassesCourseTopicRepository relClassesCourseTopicRepository;

    @Autowired
    private ClassesCourseTopicRepository classesCourseTopicRepository;

    @Autowired
    private CoursePlanTopicService coursePlanTopicService;
   
    @Transactional
    @Override
    public CourseTopic create(CourseTopic courseTopic, String month, String begin, String end, String staffId) {
        String allTargetObjectId = getTargetObjectOfAll().getId();
        if (topicIsDuplicate(allTargetObjectId, courseTopic.getTargetObjectId(), begin, end, null))
            throw new BusinessException(TOPIC_DATE_DUPLICATE, "主题课程重复。（同一段时间内，适用对象不允许重复）");


        courseTopic.setCreateId(staffId);
        courseTopic.setTopicMonth(DateUtil.parseToPattern(month, "yyyy-MM"));
        courseTopic.setBeginDate(DateUtil.parseToDate(begin));
        courseTopic.setEndDate(DateUtil.parseToDate(end));
        courseTopicRepository.save(courseTopic);
        List<Classes> classesList = classesService.getNurseryClassesListByTargetObject(allTargetObjectId, courseTopic.getTargetObjectId());
        createClassesTopic(classesList, courseTopic.getId());
        return courseTopic;
    }

    @Transactional
    @Override
    public CourseTopic modify(CourseTopic topicRequest, String month, String begin, String end) {
        TargetObject allObject = getTargetObjectOfAll();
        if (topicIsDuplicate(allObject.getId(), topicRequest.getTargetObjectId(), begin, end, topicRequest.getId()))
            throw new BusinessException(TOPIC_DATE_DUPLICATE, "主题课程重复。（同一段时间内，适用对象不允许重复）");

        Date beginDate = DateUtil.parseToDate(begin);
        Date endDate = DateUtil.parseToDate(end);
        CourseTopic courseTopic = courseTopicRepository.getOne(topicRequest.getId());
        if (courseTopic.getBeginDate().compareTo(beginDate) < 0) {
            List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateBetween(topicRequest.getId(), courseTopic.getBeginDate(), beginDate);
            if (coursePlanTopicList.size() != 0)
                throw new BusinessException(TOPIC_DATE_CANNOT_MODIFY, "主题课程时间已有排好的课程，请删除后修改时间");
        }

        if (courseTopic.getEndDate().compareTo(endDate) > 0) {
            List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateBetween(topicRequest.getId(), endDate, courseTopic.getEndDate());
            if (coursePlanTopicList.size() != 0)
                throw new BusinessException(TOPIC_DATE_CANNOT_MODIFY, "主题课程时间已有排好的课程，请删除后修改时间");
        }


        //重建课程对应班级
        if (!topicRequest.getTargetObjectId().equals(courseTopic.getTargetObjectId())) {
            //TODO 目前确定逻辑是，如果有今天以后的排的课，需要先删除排好课程，再改变适用对象，否则无法改变。

            Date todayBegin = DateUtil.getCurrentDayBeginAndEnd(new Date()).get("beg");
            List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateAfter(topicRequest.getId(), todayBegin);
            if (Objects.nonNull(coursePlanTopicList) && coursePlanTopicList.size()>0)
                throw new BusinessException(ErrorCode.TARGET_CAN_NOT_CHANGE, "请先删除今天及今天以后的排好课程，才能修改适用对象。");

//            //重新处理CoursePlanTopic和classes的关系
//            List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateAfter(topicRequest.getId(), new Date());
//            for (CoursePlanTopic coursePlanTopic : coursePlanTopicList) {
//                coursePlanTopicService.deletedByCoursePlanTopicId(coursePlanTopic.getId());
//                createClassesCourse(classesList, coursePlanTopic.getId());
//            }
//
//            //重新处理topic和classes的关系
            List<Classes> classesList = classesService.getNurseryClassesListByTargetObject(allObject.getId(), topicRequest.getTargetObjectId());
            relClassesCourseTopicRepository.deleteByTopicId(courseTopic.getId());
            createClassesTopic(classesList, courseTopic.getId());

        }
        courseTopic.merge(topicRequest);
        courseTopic.setBeginDate(DateUtil.parseToDate(begin));
        courseTopic.setEndDate(DateUtil.parseToDate(end));
        courseTopic.setTopicMonth(DateUtil.parseToPattern(month, "yyyy-MM"));
        return courseTopicRepository.save(courseTopic);
    }

    public void createClassesCourse(List<Classes> classesList, String coursePlanTopicId) {
        classesList.stream().forEach(c->coursePlanTopicService.createClassesCourse(coursePlanTopicId, c.getId(), c.getAreaId()));
    }

    public void createClassesTopic(List<Classes> classesList, String topicId) {
        classesList.stream().forEach(c->relClassesCourseTopicRepository.save(RelClassesCourseTopic.of(c.getId(), topicId)));
    }



    @Override
    public Page<CourseTopicPageVo> page(CourseTopicQuery query) {
        List<Object[]> objects = targetObjectCourseRepository.findByCourseTopicPage(query);
        Long count = targetObjectCourseRepository.countByCourseTopicPage(query);
        List<CourseTopicPageVo> pageVoList = objects.stream().map(o -> CourseTopicPageVo.of(o)).collect(Collectors.toList());
        return new PageImpl<CourseTopicPageVo>(pageVoList, PageRequest.of(query.getPageNum(), query.getPageSize()), count);
    }

    @Override
    public CourseTopic detail(String topicId) {
        CourseTopic topic = courseTopicRepository.getOne(topicId);
        return topic;
    }

    @Override
    public List<CoursePlanTopic> getCoursePlanList(String topicId) {
        List<CoursePlanTopic> coursePlanNurseryList = coursePlanTopicRepository.findByTopicIdOrderByCourseDateAsc(topicId);
        CourseTopic topic = courseTopicRepository.getOne(topicId);
        for (CoursePlanTopic nursery : coursePlanNurseryList) {
            nursery.setTopicName(topic.getName());
        }
        return coursePlanNurseryList;
    }

    @Override
    public List<TargetObject> getTargetObject() {
        return targetObjectRepository.findByDeletedOrderByCodeAsc(false);
    }

    @Override
    public TargetObject getTargetObjectOfAll() {
        return targetObjectRepository.findByName("全部");
    }


    public Boolean topicIsDuplicate(String allTargetObjectId, String targetObjectId, String begin, String end, String topicId) {
        if (StringUtils.isNotBlank(topicId)) {
            if (allTargetObjectId.equals(targetObjectId)) {
                List<CourseTopic> topicList = courseTopicRepository.findByBeginDateLessThanEqualAndEndDateGreaterThanEqualAndIdNot(DateUtil.parseToDate(end), DateUtil.parseToDate(begin), topicId);
                if (topicList.size() == 0)
                    return false;
            } else {
                List<CourseTopic> topicList = courseTopicRepository.findByTargetObjectIdInAndBeginDateLessThanEqualAndEndDateGreaterThanEqualAndIdNot(new String[]{targetObjectId, allTargetObjectId}, DateUtil.parseToDate(end), DateUtil.parseToDate(begin), topicId);
                if (topicList.size() == 0)
                    return false;
            }
        } else {
            if (allTargetObjectId.equals(targetObjectId)) {
                List<CourseTopic> topicList = courseTopicRepository.findByBeginDateLessThanEqualAndEndDateGreaterThanEqual(DateUtil.parseToDate(end), DateUtil.parseToDate(begin));
                if (topicList.size() == 0)
                    return false;
            } else {
                List<CourseTopic> topicList = courseTopicRepository.findByTargetObjectIdInAndBeginDateLessThanEqualAndEndDateGreaterThanEqual(new String[]{targetObjectId, allTargetObjectId}, DateUtil.parseToDate(end), DateUtil.parseToDate(begin));
                if (topicList.size() == 0)
                    return false;
            }
        }
        return true;
    }


    @Override
    public List<WebCourseTopicClassesVo> topicByMonth(String areaId) {
        Date today = new Date();
        List<WebCourseTopicClassesVo> courseTopicClassesList = Lists.newArrayList();
        List<CourseTopic> topicList = courseTopicRepository.findByBeginDateLessThanEqualAndEndDateGreaterThanEqual(today, today);
        for (CourseTopic topic : topicList) {
        	List<ClassesTopicDO> classesTopicDOS=new ArrayList<ClassesTopicDO>();
        	TargetObject targetObect = targetObjectRepository.getOne(topic.getTargetObjectId());
        	if("全部".equals(targetObect.getName())){
        		//ssoCallService.getAreaById(areaId);
        		 List<ClassesVo> classVO=classesService.getClassesByArea(areaId);
        	     for(int i=0;i<classVO.size();i++){
        	    	 ClassesTopicDO classesTopicDO=new ClassesTopicDO();
        	    	 classesTopicDO.setAreaId(areaId);
        	    	 classesTopicDO.setClassesId(classVO.get(i).getId());
        	    	 classesTopicDO.setClassesName(classVO.get(i).getName());
        	    	 classesTopicDOS.add(classesTopicDO);
        	     }
        		 courseTopicClassesList.add(WebCourseTopicClassesVo.of(topic, classesTopicDOS));
        		 return courseTopicClassesList;
        	}
        	classesTopicDOS = classesCourseTopicRepository.findByTopic(topic.getId(), areaId);
            courseTopicClassesList.add(WebCourseTopicClassesVo.of(topic, classesTopicDOS));
        }
        return courseTopicClassesList;
    }

    @Transactional
    @Override
    public Boolean cleanClassesTopicCourse(Classes classes, String oldTargetObjectId, String targetObjectId) {
        String allTargetObjectId = getTargetObjectOfAll().getId();
        Date now = new Date();

        //清除原有课程
        if (StringUtils.isNotBlank(oldTargetObjectId)) {
            //获取往后的主题
            List<CourseTopic> topicList = getAfterTopicList(allTargetObjectId, oldTargetObjectId, now);
            for (CourseTopic topic : topicList) {
                //删除相关班级的课程
                List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateAfter(topic.getId(), now);
                for (CoursePlanTopic c : coursePlanTopicList) {
                    coursePlanTopicService.deletedByCoursePlanTopicAndClasses(c.getId(), classes.getId());
                }
                //删除往后时间的相关主题
                relClassesCourseTopicRepository.deleteByTopicIdAndClassesId(topic.getId(), classes.getId());
            }
        }
        //创建新的课程
        List<CourseTopic> newTopicList = getAfterTopicList(allTargetObjectId, targetObjectId, now);
//        List<Classes> classesList = classesService.getNurseryClassesListByTargetObject(allTargetObjectId, targetObjectId);
        for (CourseTopic topic : newTopicList) {
            List<CoursePlanTopic> coursePlanTopicList = coursePlanTopicRepository.findByTopicIdAndCourseDateAfter(topic.getId(), now);
            for (CoursePlanTopic coursePlanTopic : coursePlanTopicList) {
                coursePlanTopicService.createClassesCourse(coursePlanTopic.getId(), classes.getId(), classes.getAreaId());
//                createClassesCourse(classesList, coursePlanTopic.getId());
            }
            relClassesCourseTopicRepository.save(RelClassesCourseTopic.of(classes.getId(), topic.getId()));
        }

        return true;
    }


    public List<CourseTopic> getAfterTopicList(String allTargetObjectId, String targetObjectId, Date today) {
        List<CourseTopic> list = Lists.newArrayList();

        //对应对象后面的月份
        List<CourseTopic> topicList = courseTopicRepository.findByTargetObjectIdAndBeginDateAfter(targetObjectId, today);
        if (Objects.nonNull(topicList) && topicList.size()!=0)
            list.addAll(topicList);

        //对应对象当月
        CourseTopic courseTopic = courseTopicRepository.findByTargetObjectIdAndBeginDateLessThanEqualAndEndDateGreaterThanEqual(targetObjectId, today, today);
        if (Objects.nonNull(courseTopic))
            list.add(courseTopic);

        //主题课程为全部后面的月份
        List<CourseTopic> allTopicList = courseTopicRepository.findByTargetObjectIdAndBeginDateAfter(allTargetObjectId, today);
        if (Objects.nonNull(allTopicList) && allTopicList.size()!=0)
            list.addAll(allTopicList);
        //主题课程为全部当月
        CourseTopic allCourseTopic = courseTopicRepository.findByTargetObjectIdAndBeginDateLessThanEqualAndEndDateGreaterThanEqual(allTargetObjectId, today, today);
        if (Objects.nonNull(allCourseTopic))
            list.add(allCourseTopic);
        return list;
    }
}
